/**
 * @Title: BitMapUtil.java
 * @Package com.clt.runman.utils
 * @Description: TODO(用一句话描述该文件做什么)
 * @author A18ccms A18ccms_gmail_com
 * @date 2015年5月18日 下午8:12:27
 * @Copyright:Copyright (c)
 * @Company:whty李焱生
 * @version V1.0
 */
package com.xiaoge.basedevlibrary.utils;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;

/**
 *@Description:BitMapUtil--异步加载本地图片
 *@Author:李焱生
 *@Since:2015年5月18日下午8:12:27  
 */
public class BitMapUtil {
    private static final Options    OPTIONS_GET_SIZE = new Options ();
    private static final Options    OPTIONS_DECODE   = new Options ();
    private static final byte[]     LOCKED           = new byte[0];
    // 此对象用来保持Bitmap的回收顺序,保证最后使用的图片被回收
    private static final LinkedList CACHE_ENTRIES    = new LinkedList ();
    // 线程请求创建图片的队列
    private static final Queue      TASK_QUEUE       = new LinkedList ();
    // 保存队列中正在处理的图片的key,有效防止重复添加到请求创建队列
    private static final Set        TASK_QUEUE_INDEX = new HashSet ();
    // 缓存Bitmap
    private static final Map        IMG_CACHE_INDEX  = new HashMap ();   // 通过图片路径,图片大小
    // 缓存图片的大小
    private static int              CACHE_SIZE       = 20;               // 缓存图片数量
    static {
        OPTIONS_GET_SIZE.inJustDecodeBounds = true;
        // 初始化创建图片线程,并等待处理
        new Thread () {

            {
                setDaemon (true);
            }

            public void run(){
                while (true) {
                    synchronized (TASK_QUEUE) {
                        if (TASK_QUEUE.isEmpty ()) {
                            try {
                                TASK_QUEUE.wait ();
                            } catch (InterruptedException e) {
                                e.printStackTrace ();
                            }
                        }
                    }
                    QueueEntry entry = (QueueEntry) TASK_QUEUE.poll ();
                    String key = createKey (entry.path);
                    TASK_QUEUE_INDEX.remove (key);
                }
            }
        }.start ();
    }

    public static Bitmap getBitmap(String path){
        if (path == null) { return null; }
        Bitmap bitMap = null;
        try {
            if (CACHE_ENTRIES.size () >= CACHE_SIZE) {
                destoryLast ();
            }
            bitMap = useBitmap (path);
            if (bitMap != null && !bitMap.isRecycled ()) { return bitMap; }
            bitMap = createBitmap (path);
            String key = createKey (path);
            synchronized (LOCKED) {
                IMG_CACHE_INDEX.put (key, bitMap);
                CACHE_ENTRIES.addFirst (key);
            }
        } catch (OutOfMemoryError err) {
            destoryLast ();
            return createBitmap (path);
        }
        return bitMap;
    }

    // ------------------------------------------------------------------ private Methods
    // 将图片加入队列头
    private static Bitmap useBitmap(String path){
        Bitmap bitMap = null;
        String key = createKey (path);
        synchronized (LOCKED) {
            bitMap = (Bitmap) IMG_CACHE_INDEX.get (key);
            if (null != bitMap) {
                if (CACHE_ENTRIES.remove (key)) {
                    CACHE_ENTRIES.addFirst (key);
                }
            }
        }
        return bitMap;
    }

    // 回收最后一张图片
    private static void destoryLast(){
        synchronized (LOCKED) {
            String key = (String) CACHE_ENTRIES.removeLast ();
            if (key.length () > 0) {
                Bitmap bitMap = (Bitmap) IMG_CACHE_INDEX.remove (key);
                if (bitMap != null && !bitMap.isRecycled ()) {
                    bitMap.recycle ();
                    bitMap = null;
                }
            }
        }
    }

    // 创建键
    private static String createKey(String path){
        if (null == path || path.length () == 0) { return ""; }
        return path;
    }

    // 通过图片路径,宽度高度创建一个Bitmap对象
    private static Bitmap createBitmap(String path){
        return PictureUtils.getBitmapByPath (path);
    }

    // 队列缓存参数对象
    static class QueueEntry {

        public String path;
    }
    
    /**
     * 
     *@Description: TODO(将四方形的图片转换成为圆形图片) 
     *@Author: 郭永振
     *@Since: 2016-10-19下午12:11:05
     *@param bitmap
     *@return
     */
    public static Bitmap toRoundBitmap(Bitmap bitmap) {  
        //圆形图片宽高  
        int width = bitmap.getWidth();  
        int height = bitmap.getHeight();  
        //正方形的边长  
        int r = 0;  
        //取最短边做边长  
        if(width > height) {  
            r = height;  
        } else {  
            r = width;  
        }  
        //构建一个bitmap  
        Bitmap backgroundBmp = Bitmap.createBitmap(width,  
                 height, Config.ARGB_8888);  
        //new一个Canvas，在backgroundBmp上画图  
        Canvas canvas = new Canvas(backgroundBmp);  
        Paint paint = new Paint();  
        //设置边缘光滑，去掉锯齿  
        paint.setAntiAlias(true);  
        //宽高相等，即正方形  
        RectF rect = new RectF(0, 0, r, r);  
        //通过制定的rect画一个圆角矩形，当圆角X轴方向的半径等于Y轴方向的半径时，  
        //且都等于r/2时，画出来的圆角矩形就是圆形  
        canvas.drawRoundRect(rect, r/2, r/2, paint);  
        //设置当两个图形相交时的模式，SRC_IN为取SRC图形相交的部分，多余的将被去掉  
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));  
        //canvas将bitmap画在backgroundBmp上  
        canvas.drawBitmap(bitmap, null, rect, paint);  
        //返回已经绘画好的backgroundBmp  
        return backgroundBmp;  
    }
}
